home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 2: Applications / Linux Cubed Series 2 - Applications.iso / utils / shell / cdialog-.9a / cdialog- / cdialog-0.9a / rc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-01-15  |  14.4 KB  |  602 lines

  1. /*
  2.  *  rc.c -- routines for processing the configuration file
  3.  *
  4.  *  AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
  5.  *
  6.  *  This program is free software; you can redistribute it and/or
  7.  *  modify it under the terms of the GNU General Public License
  8.  *  as published by the Free Software Foundation; either version 2
  9.  *  of the License, or (at your option) any later version.
  10.  *
  11.  *  This program is distributed in the hope that it will be useful,
  12.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  *  GNU General Public License for more details.
  15.  *
  16.  *  You should have received a copy of the GNU General Public License
  17.  *  along with this program; if not, write to the Free Software
  18.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  */
  20.  
  21. #include "dialog.h"
  22.  
  23. #ifdef HAVE_NCURSES
  24. #include "colors.h"
  25. /*
  26.  * For matching color names with color values
  27.  */
  28. color_names_st color_names[] =
  29. {
  30.     {"BLACK", COLOR_BLACK},
  31.     {"RED", COLOR_RED},
  32.     {"GREEN", COLOR_GREEN},
  33.     {"YELLOW", COLOR_YELLOW},
  34.     {"BLUE", COLOR_BLUE},
  35.     {"MAGENTA", COLOR_MAGENTA},
  36.     {"CYAN", COLOR_CYAN},
  37.     {"WHITE", COLOR_WHITE},
  38. };                /* color names */
  39. #endif
  40.  
  41. #define DIALOGRC ".dialogrc"
  42. #define VAR_LEN 30
  43. #define COMMENT_LEN 70
  44.  
  45. /* Types of values */
  46. #define VAL_INT  0
  47. #define VAL_STR  1
  48. #define VAL_BOOL 2
  49. #define VAL_ATTR 3
  50.  
  51. /* Type of line in configuration file */
  52. #define LINE_BLANK    2
  53. #define LINE_COMMENT  1
  54. #define LINE_OK       0
  55. #define LINE_ERROR   -1
  56.  
  57. /* number of configuration variables */
  58. #define VAR_COUNT        (sizeof(vars) / sizeof(vars_st))
  59.  
  60. /* check if character is white space */
  61. #define whitespace(c)    (c == ' ' || c == '\t')
  62.  
  63. /* check if character is string quoting characters */
  64. #define isquote(c)       (c == '"' || c == '\'')
  65.  
  66. /* get last character of string */
  67. #define lastch(str)      str[strlen(str)-1]
  68.  
  69. /*
  70.  * Configuration variables
  71.  */
  72. typedef struct {
  73.     char name[VAR_LEN];        /* name of configuration variable as in DIALOGRC */
  74.     void *var;            /* address of actually variable to change */
  75.     int type;            /* type of value */
  76.     char comment[COMMENT_LEN];    /* comment to put in "rc" file */
  77. } vars_st;
  78.  
  79. vars_st vars[] =
  80. {
  81.     {"use_shadow",
  82.      &use_shadow,
  83.      VAL_BOOL,
  84.      "Shadow dialog boxes? This also turns on color."},
  85.  
  86.     {"use_colors",
  87.      &use_colors,
  88.      VAL_BOOL,
  89.      "Turn color support ON or OFF"},
  90.  
  91.     {"screen_color",
  92.      color_table[0],
  93.      VAL_ATTR,
  94.      "Screen color"},
  95.  
  96.     {"shadow_color",
  97.      color_table[1],
  98.      VAL_ATTR,
  99.      "Shadow color"},
  100.  
  101.     {"dialog_color",
  102.      color_table[2],
  103.      VAL_ATTR,
  104.      "Dialog box color"},
  105.  
  106.     {"title_color",
  107.      color_table[3],
  108.      VAL_ATTR,
  109.      "Dialog box title color"},
  110.  
  111.     {"border_color",
  112.      color_table[4],
  113.      VAL_ATTR,
  114.      "Dialog box border color"},
  115.  
  116.     {"button_active_color",
  117.      color_table[5],
  118.      VAL_ATTR,
  119.      "Active button color"},
  120.  
  121.     {"button_inactive_color",
  122.      color_table[6],
  123.      VAL_ATTR,
  124.      "Inactive button color"},
  125.  
  126.     {"button_key_active_color",
  127.      color_table[7],
  128.      VAL_ATTR,
  129.      "Active button key color"},
  130.  
  131.     {"button_key_inactive_color",
  132.      color_table[8],
  133.      VAL_ATTR,
  134.      "Inactive button key color"},
  135.  
  136.     {"button_label_active_color",
  137.      color_table[9],
  138.      VAL_ATTR,
  139.      "Active button label color"},
  140.  
  141.     {"button_label_inactive_color",
  142.      color_table[10],
  143.      VAL_ATTR,
  144.      "Inactive button label color"},
  145.  
  146.     {"inputbox_color",
  147.      color_table[11],
  148.      VAL_ATTR,
  149.      "Input box color"},
  150.  
  151.     {"inputbox_border_color",
  152.      color_table[12],
  153.      VAL_ATTR,
  154.      "Input box border color"},
  155.  
  156.     {"searchbox_color",
  157.      color_table[13],
  158.      VAL_ATTR,
  159.      "Search box color"},
  160.  
  161.     {"searchbox_title_color",
  162.      color_table[14],
  163.      VAL_ATTR,
  164.      "Search box title color"},
  165.  
  166.     {"searchbox_border_color",
  167.      color_table[15],
  168.      VAL_ATTR,
  169.      "Search box border color"},
  170.  
  171.     {"position_indicator_color",
  172.      color_table[16],
  173.      VAL_ATTR,
  174.      "File position indicator color"},
  175.  
  176.     {"menubox_color",
  177.      color_table[17],
  178.      VAL_ATTR,
  179.      "Menu box color"},
  180.  
  181.     {"menubox_border_color",
  182.      color_table[18],
  183.      VAL_ATTR,
  184.      "Menu box border color"},
  185.  
  186.     {"item_color",
  187.      color_table[19],
  188.      VAL_ATTR,
  189.      "Item color"},
  190.  
  191.     {"item_selected_color",
  192.      color_table[20],
  193.      VAL_ATTR,
  194.      "Selected item color"},
  195.  
  196.     {"tag_color",
  197.      color_table[21],
  198.      VAL_ATTR,
  199.      "Tag color"},
  200.  
  201.     {"tag_selected_color",
  202.      color_table[22],
  203.      VAL_ATTR,
  204.      "Selected tag color"},
  205.  
  206.     {"tag_key_color",
  207.      color_table[23],
  208.      VAL_ATTR,
  209.      "Tag key color"},
  210.  
  211.     {"tag_key_selected_color",
  212.      color_table[24],
  213.      VAL_ATTR,
  214.      "Selected tag key color"},
  215.  
  216.     {"check_color",
  217.      color_table[25],
  218.      VAL_ATTR,
  219.      "Check box color"},
  220.  
  221.     {"check_selected_color",
  222.      color_table[26],
  223.      VAL_ATTR,
  224.      "Selected check box color"},
  225.  
  226.     {"uarrow_color",
  227.      color_table[27],
  228.      VAL_ATTR,
  229.      "Up arrow color"},
  230.  
  231.     {"darrow_color",
  232.      color_table[28],
  233.      VAL_ATTR,
  234.      "Down arrow color"}
  235. };                /* vars */
  236.  
  237. static char *attr_to_str (int fg, int bg, int hl);
  238. static int str_to_attr (char *str, int *fg, int *bg, int *hl);
  239. static int parse_line (char *line, char **var, char **value);
  240.  
  241. /*
  242.  * Create the configuration file
  243.  */
  244. void
  245. create_rc (const char *filename)
  246. {
  247.     int i;
  248.     FILE *rc_file;
  249.  
  250.     if ((rc_file = fopen (filename, "wt")) == NULL)
  251.     exiterr ("\nError opening file for writing in create_rc().\n");
  252.  
  253.     fprintf (rc_file, "#\
  254. \n# Run-time configuration file for dialog\
  255. \n#\
  256. \n# Automatically generated by \"dialog --create-rc <file>\"\
  257. \n#\
  258. \n#\
  259. \n# Types of values:\
  260. \n#\
  261. \n# Number     -  <number>\
  262. \n# String     -  \"string\"\
  263. \n# Boolean    -  <ON|OFF>\
  264. \n# Attribute  -  (foreground,background,highlight?)\
  265. \n#\n\n");
  266.  
  267.     /* Print an entry for each configuration variable */
  268.     for (i = 0; i < VAR_COUNT; i++) {
  269.     fprintf (rc_file, "\n# %s\n", vars[i].comment);
  270.     switch (vars[i].type) {
  271.     case VAL_INT:
  272.         fprintf (rc_file, "%s = %d\n", vars[i].name,
  273.              *((int *) vars[i].var));
  274.         break;
  275.     case VAL_STR:
  276.         fprintf (rc_file, "%s = \"%s\"\n", vars[i].name,
  277.              (char *) vars[i].var);
  278.         break;
  279.     case VAL_BOOL:
  280.         fprintf (rc_file, "%s = %s\n", vars[i].name,
  281.              *((bool *) vars[i].var) ? "ON" : "OFF");
  282.         break;
  283.     case VAL_ATTR:
  284.         fprintf (rc_file, "%s = %s\n", vars[i].name,
  285.              attr_to_str (((int *) vars[i].var)[0],
  286.                ((int *) vars[i].var)[1], ((int *) vars[i].var)[2]));
  287.         break;
  288.     }
  289.     }
  290.  
  291.     fclose (rc_file);
  292. }
  293.  
  294.  
  295. /*
  296.  * Parse the configuration file and set up variables
  297.  */
  298. int
  299. parse_rc (void)
  300. {
  301.     int i, l = 1, parse, fg, bg, hl;
  302.     char str[MAX_LEN + 1], *var, *value, *tempptr;
  303.     FILE *rc_file;
  304.  
  305.     /*
  306.  
  307.      *  At start, 'dialog' determines the settings to use as follows:
  308.      *
  309.      *  a) if environment variable DIALOGRC is set, it's value determines the
  310.      *     name of the configuration file.
  311.      *
  312.      *  b) if the file in (a) can't be found, use the file $HOME/.dialogrc
  313.      *     as the configuration file.
  314.      *
  315.      *  c) if the file in (b) can't be found, use compiled in defaults.
  316.      *
  317.      */
  318.  
  319.     if ((tempptr = getenv ("DIALOGRC")) != NULL)
  320.     rc_file = fopen (tempptr, "rt");
  321.  
  322.     if (tempptr == NULL || rc_file == NULL) {    /* step (a) failed? */
  323.     /* try step (b) */
  324.     if ((tempptr = getenv ("HOME")) == NULL)
  325.         return 0;        /* step (b) failed, use default values */
  326.  
  327.     if (tempptr[0] == '\0' || lastch (tempptr) == '/')
  328.         sprintf (str, "%s%s", tempptr, DIALOGRC);
  329.     else
  330.         sprintf (str, "%s/%s", tempptr, DIALOGRC);
  331.  
  332.     if ((rc_file = fopen (str, "rt")) == NULL)
  333.         return 0;        /* step (b) failed, use default values */
  334.     }
  335.     /* Scan each line and set variables */
  336.     while (fgets (str, MAX_LEN, rc_file) != NULL) {
  337.     if (lastch (str) != '\n') {
  338.         /* ignore rest of file if line too long */
  339.         fprintf (stderr, "\nParse error: line %d of configuration"
  340.              " file too long.\n", l);
  341.         fclose (rc_file);
  342.         return -1;        /* parse aborted */
  343.     } else {
  344.         lastch (str) = '\0';
  345.         parse = parse_line (str, &var, &value);    /* parse current line */
  346.  
  347.         switch (parse) {
  348.         case LINE_BLANK:    /* ignore blank lines and comments */
  349.         case LINE_COMMENT:
  350.         break;
  351.         case LINE_OK:
  352.         /* search table for matching config variable name */
  353.         for (i = 0; i < VAR_COUNT && strcmp (vars[i].name, var); i++);
  354.  
  355.         if (i == VAR_COUNT) {    /* no match */
  356.             fprintf (stderr, "\nParse error: unknown variable "
  357.                  "at line %d of configuration file.\n", l);
  358.             return -1;    /* parse aborted */
  359.         } else {    /* variable found in table, set run time variables */
  360.             switch (vars[i].type) {
  361.             case VAL_INT:
  362.             *((int *) vars[i].var) = atoi (value);
  363.             break;
  364.             case VAL_STR:
  365.             if (!isquote (value[0]) || !isquote (lastch (value))
  366.                 || strlen (value) < 2) {
  367.                 fprintf (stderr, "\nParse error: string value "
  368.                      "expected at line %d of configuration "
  369.                      "file.\n", l);
  370.                 return -1;    /* parse aborted */
  371.             } else {
  372.                 /* remove the (") quotes */
  373.                 value++;
  374.                 lastch (value) = '\0';
  375.                 strcpy ((char *) vars[i].var, value);
  376.             }
  377.             break;
  378.             case VAL_BOOL:
  379.             if (!strcasecmp (value, "ON"))
  380.                 *((bool *) vars[i].var) = TRUE;
  381.             else if (!strcasecmp (value, "OFF"))
  382.                 *((bool *) vars[i].var) = FALSE;
  383.             else {
  384.                 fprintf (stderr, "\nParse error: boolean value "
  385.                      "expected at line %d of configuration "
  386.                      "file.\n", l);
  387.                 return -1;    /* parse aborted */
  388.             }
  389.             break;
  390.             case VAL_ATTR:
  391.             if (str_to_attr (value, &fg, &bg, &hl) == -1) {
  392.                 fprintf (stderr, "\nParse error: attribute "
  393.                    "value expected at line %d of configuration "
  394.                      "file.\n", l);
  395.                 return -1;    /* parse aborted */
  396.             }
  397.             ((int *) vars[i].var)[0] = fg;
  398.             ((int *) vars[i].var)[1] = bg;
  399.             ((int *) vars[i].var)[2] = hl;
  400.             break;
  401.             }
  402.         }
  403.         break;
  404.         case LINE_ERROR:
  405.         fprintf (stderr, "\nParse error: syntax error at line %d of "
  406.              "configuration file.\n", l);
  407.         return -1;    /* parse aborted */
  408.         }
  409.     }
  410.     l++;            /* next line */
  411.     }
  412.  
  413.     fclose (rc_file);
  414.     return 0;            /* parse successful */
  415. }
  416.  
  417. /*
  418.  * Convert an attribute to a string representation like this:
  419.  *
  420.  * "(foreground,background,highlight)"
  421.  */
  422. static char *
  423. attr_to_str (int fg, int bg, int hl)
  424. {
  425.     int i;
  426.     static char str[MAX_LEN + 1];
  427.  
  428.     strcpy (str, "(");
  429.     /* foreground */
  430.     for (i = 0; fg != color_names[i].value; i++);
  431.     strcat (str, color_names[i].name);
  432.     strcat (str, ",");
  433.  
  434.     /* background */
  435.     for (i = 0; bg != color_names[i].value; i++);
  436.     strcat (str, color_names[i].name);
  437.  
  438.     /* highlight */
  439.     strcat (str, hl ? ",ON)" : ",OFF)");
  440.  
  441.     return str;
  442. }
  443.  
  444. /*
  445.  * Extract the foreground, background and highlight values from an attribute
  446.  * represented as a string in this form:
  447.  *
  448.  * "(foreground,background,highlight)"
  449.  */
  450. static int
  451. str_to_attr (char *str, int *fg, int *bg, int *hl)
  452. {
  453.     int i = 0, j, get_fg = 1;
  454.     char tempstr[MAX_LEN + 1], *part;
  455.  
  456.     if (str[0] != '(' || lastch (str) != ')')
  457.     return -1;        /* invalid representation */
  458.  
  459.     /* remove the parenthesis */
  460.     strcpy (tempstr, str + 1);
  461.     lastch (tempstr) = '\0';
  462.  
  463.  
  464.     /* get foreground and background */
  465.  
  466.     while (1) {
  467.     /* skip white space before fg/bg string */
  468.     while (whitespace (tempstr[i]) && tempstr[i] != '\0')
  469.         i++;
  470.     if (tempstr[i] == '\0')
  471.         return -1;        /* invalid representation */
  472.     part = tempstr + i;    /* set 'part' to start of fg/bg string */
  473.  
  474.     /* find end of fg/bg string */
  475.     while (!whitespace (tempstr[i]) && tempstr[i] != ','
  476.            && tempstr[i] != '\0')
  477.         i++;
  478.  
  479.     if (tempstr[i] == '\0')
  480.         return -1;        /* invalid representation */
  481.     else if (whitespace (tempstr[i])) {    /* not yet ',' */
  482.         tempstr[i++] = '\0';
  483.  
  484.         /* skip white space before ',' */
  485.         while (whitespace (tempstr[i]) && tempstr[i] != '\0')
  486.         i++;
  487.  
  488.         if (tempstr[i] != ',')
  489.         return -1;    /* invalid representation */
  490.     }
  491.     tempstr[i++] = '\0';    /* skip the ',' */
  492.     for (j = 0; j < COLOR_COUNT && strcasecmp (part, color_names[j].name);
  493.          j++);
  494.     if (j == COLOR_COUNT)    /* invalid color name */
  495.         return -1;
  496.     if (get_fg) {
  497.         *fg = color_names[j].value;
  498.         get_fg = 0;        /* next we have to get the background */
  499.     } else {
  500.         *bg = color_names[j].value;
  501.         break;
  502.     }
  503.     }                /* got foreground and background */
  504.  
  505.  
  506.     /* get highlight */
  507.  
  508.     /* skip white space before highlight string */
  509.     while (whitespace (tempstr[i]) && tempstr[i] != '\0')
  510.     i++;
  511.     if (tempstr[i] == '\0')
  512.     return -1;        /* invalid representation */
  513.     part = tempstr + i;        /* set 'part' to start of highlight string */
  514.  
  515.     /* trim trailing white space from highlight string */
  516.     i = strlen (part) - 1;
  517.     while (whitespace (part[i]))
  518.     i--;
  519.     part[i + 1] = '\0';
  520.  
  521.     if (!strcasecmp (part, "ON"))
  522.     *hl = TRUE;
  523.     else if (!strcasecmp (part, "OFF"))
  524.     *hl = FALSE;
  525.     else
  526.     return -1;        /* invalid highlight value */
  527.  
  528.     return 0;
  529. }
  530.  
  531.  
  532. /*
  533.  * Parse a line in the configuration file
  534.  *
  535.  * Each line is of the form:  "variable = value". On exit, 'var' will contain
  536.  * the variable name, and 'value' will contain the value string.
  537.  *
  538.  * Return values:
  539.  *
  540.  * LINE_BLANK   - line is blank
  541.  * LINE_COMMENT - line is comment
  542.  * LINE_OK      - line is ok
  543.  * LINE_ERROR   - syntax error in line
  544.  */
  545. static int
  546. parse_line (char *line, char **var, char **value)
  547. {
  548.     int i = 0;
  549.  
  550.     /* ignore white space at beginning of line */
  551.     while (whitespace (line[i]) && line[i] != '\0')
  552.     i++;
  553.  
  554.     if (line[i] == '\0')    /* line is blank */
  555.     return LINE_BLANK;
  556.     else if (line[i] == '#')    /* line is comment */
  557.     return LINE_COMMENT;
  558.     else if (line[i] == '=')    /* variables names can't strart with a '=' */
  559.     return LINE_ERROR;
  560.  
  561.     /* set 'var' to variable name */
  562.     *var = line + i++;        /* skip to next character */
  563.  
  564.     /* find end of variable name */
  565.     while (!whitespace (line[i]) && line[i] != '=' && line[i] != '\0')
  566.     i++;
  567.  
  568.     if (line[i] == '\0')    /* syntax error */
  569.     return LINE_ERROR;
  570.     else if (line[i] == '=')
  571.     line[i++] = '\0';
  572.     else {
  573.     line[i++] = '\0';
  574.  
  575.     /* skip white space before '=' */
  576.     while (whitespace (line[i]) && line[i] != '\0')
  577.         i++;
  578.  
  579.     if (line[i] != '=')    /* syntax error */
  580.         return LINE_ERROR;
  581.     else
  582.         i++;        /* skip the '=' */
  583.     }
  584.  
  585.     /* skip white space after '=' */
  586.     while (whitespace (line[i]) && line[i] != '\0')
  587.     i++;
  588.  
  589.     if (line[i] == '\0')
  590.     return LINE_ERROR;
  591.     else
  592.     *value = line + i;    /* set 'value' to value string */
  593.  
  594.     /* trim trailing white space from 'value' */
  595.     i = strlen (*value) - 1;
  596.     while (whitespace ((*value)[i]))
  597.     i--;
  598.     (*value)[i + 1] = '\0';
  599.  
  600.     return LINE_OK;        /* no syntax error in line */
  601. }
  602.